local Made = require 'packages/mamashengde/record/baseme'

-- 定义事件数据类
---@class MaryokuChangingDataSpec
---@field who ServerPlayer
---@field num integer
---@field old_value integer
---@field new_value integer
---@field reason string

---@class MaryokuChangingData: MaryokuChangingDataSpec, TriggerData
local MaryokuChangingData = TriggerData:subclass("MaryokuChangingData")

---@class MaryokuChangedDataSpec
---@field who ServerPlayer
---@field num integer
---@field old_value integer
---@field new_value integer
---@field reason string

---@class MaryokuChangedData: MaryokuChangedDataSpec, TriggerData
local MaryokuChangedData = TriggerData:subclass("MaryokuChangedData")

---@class MaryokuMaxChangedDataSpec
---@field who ServerPlayer
---@field old_max integer
---@field new_max integer
---@field reason string

---@class MaryokuMaxChangedData: MaryokuMaxChangedDataSpec, TriggerData
local MaryokuMaxChangedData = TriggerData:subclass("MaryokuMaxChangedData")

---@class HenshinEnteringDataSpec
---@field who ServerPlayer
---@field target_general string
---@field reason string

---@class HenshinEnteringData: HenshinEnteringDataSpec, TriggerData
local HenshinEnteringData = TriggerData:subclass("HenshinEnteringData")

---@class HenshinEnteredDataSpec
---@field who ServerPlayer
---@field original_general string
---@field target_general string
---@field reason string

---@class HenshinEnteredData: HenshinEnteredDataSpec, TriggerData
local HenshinEnteredData = TriggerData:subclass("HenshinEnteredData")

---@class HenshinExitingDataSpec
---@field who ServerPlayer
---@field reason string

---@class HenshinExitingData: HenshinExitingDataSpec, TriggerData
local HenshinExitingData = TriggerData:subclass("HenshinExitingData")

---@class HenshinExitedDataSpec
---@field who ServerPlayer
---@field reason string
---@field from_general string
---@field to_general string

---@class HenshinExitedData: HenshinExitedDataSpec, TriggerData
local HenshinExitedData = TriggerData:subclass("HenshinExitedData")

---@class MaryokuConsumedDataSpec
---@field who ServerPlayer
---@field num integer
---@field reason string

---@class MaryokuConsumedData: MaryokuConsumedDataSpec, TriggerData
local MaryokuConsumedData = TriggerData:subclass("MaryokuConsumedData")

-- 定义事件类
---@class MaryokuChanging: TriggerEvent
---@field data MaryokuChangingData
local MaryokuChanging = TriggerEvent:subclass("MaryokuChanging")

---@class MaryokuChanged: TriggerEvent
---@field data MaryokuChangedData
local MaryokuChanged = TriggerEvent:subclass("MaryokuChanged")

---@class MaryokuMaxChanged: TriggerEvent
---@field data MaryokuMaxChangedData
local MaryokuMaxChanged = TriggerEvent:subclass("MaryokuMaxChanged")

---@class HenshinEntering: TriggerEvent
---@field data HenshinEnteringData
local HenshinEntering = TriggerEvent:subclass("HenshinEntering")

---@class HenshinEntered: TriggerEvent
---@field data HenshinEnteredData
local HenshinEntered = TriggerEvent:subclass("HenshinEntered")

---@class HenshinExiting: TriggerEvent
---@field data HenshinExitingData
local HenshinExiting = TriggerEvent:subclass("HenshinExiting")

---@class HenshinExited: TriggerEvent
---@field data HenshinExitedData
local HenshinExited = TriggerEvent:subclass("HenshinExited")

---@class MaryokuConsumed: TriggerEvent
---@field data MaryokuConsumedData
local MaryokuConsumed = TriggerEvent:subclass("MaryokuConsumed")

-- 将事件保存到 Made 表中
Made.MaryokuChanging = MaryokuChanging
Made.MaryokuChanged = MaryokuChanged
Made.MaryokuMaxChanged = MaryokuMaxChanged
Made.HenshinEntering = HenshinEntering
Made.HenshinEntered = HenshinEntered
Made.HenshinExiting = HenshinExiting
Made.HenshinExited = HenshinExited
Made.MaryokuConsumed = MaryokuConsumed

-- 变身技标签，当变身技的魔力达到上限时角色可以于对应时机进行变身，在魔力消耗为0时变回原来的形态
Made.HenshinSkill = "henshin_skill"

Fk:loadTranslationTable{
  ["#made_henshin_skill"] = "满足条件获得魔力；魔力达到上限时，你可以在对应的时间点进行变身；魔力消耗至0时，你退出变身。变身前后的形态体力独立计算。",
  ["@shine__maryoku"] = "魔力",
  ["#HenshinInvalidTarget"] = "%from 的变身目标武将不存在",
  ["#HenshinDataCorrupted"] = "%from 的变身数据损坏，无法正常退出变身状态",
}

-- 检查角色是否处于变身状态
---@param player Player
---@return boolean
Made.isHenshin = function(player)
    return player:getMark("shine__henshin_state") > 0
end

-- 获取角色当前魔力值
---@param player Player
---@return integer
Made.getMaryoku = function(player)
    return player:getMark("shine__maryoku") or 0
end

-- 获取角色魔力上限
---@param player Player
---@return integer
Made.getMaryokuMax = function(player)
    return player:getMark("shine__maryoku_max") or 0
end

-- 修正 changeMaryoku 函数，移除 skill_name 参数
---@param player ServerPlayer 被改变魔力的角色
---@param num integer 变化值
---@param reason string 原因（通常为技能名）
Made.changeMaryoku = function(player, num, reason)
    local room = player.room
    local old_value = Made.getMaryoku(player)
    local max_value = Made.getMaryokuMax(player)
    
    local new_value = math.max(0, math.min(max_value, old_value + num))
    
    -- 触发魔力变化前事件
    local pre_data = MaryokuChangingData:new{
        who = player,
        num = num,
        old_value = old_value,
        new_value = new_value,
        reason = reason
    }
    room.logic:trigger(Made.MaryokuChanging, player, pre_data)
    
    -- 如果事件中被阻止，则返回
    if pre_data.prevented then return end
    
    -- 实际改变魔力
    local actual_change = pre_data.new_value - old_value
    if actual_change ~= 0 then
        room:setPlayerMark(player, "shine__maryoku", pre_data.new_value)
        room:setPlayerMark(player, "@shine__maryoku", (max_value == 0 and pre_data.new_value == 0) and 0 or (pre_data.new_value.."/"..max_value))
        
        -- 触发魔力变化后事件
        local post_data = MaryokuChangedData:new{
            who = player,
            num = actual_change,
            old_value = old_value,
            new_value = pre_data.new_value,
            reason = reason
        }
        room.logic:trigger(Made.MaryokuChanged, player, post_data)
        
        -- 如果是魔力消耗，触发消耗事件
        if actual_change < 0 then
            local consumed_data = MaryokuConsumedData:new{
                who = player,
                num = math.abs(actual_change),
                reason = reason
            }
            room.logic:trigger(Made.MaryokuConsumed, player, consumed_data)
        end
        
        -- 检查是否需要退出变身状态
        if Made.isHenshin(player) and post_data.new_value == 0 then
            Made.exitHenshin(player, "maryoku_zero")
        end
    end
end

-- 设置魔力上限
---@param player ServerPlayer 被改变魔力上限的角色
---@param max integer 上限值
---@param reason string 原因（通常为技能名）
Made.setMaryokuMax = function(player, max, reason)
    local room = player.room
    local value = Made.getMaryoku(player)
    local old_max = Made.getMaryokuMax(player)
    
    room:setPlayerMark(player, "shine__maryoku_max", max)
    room:setPlayerMark(player, "@shine__maryoku", (max == 0 and value == 0) and 0 or (value.."/"..max))
    
    -- 如果当前魔力超过新上限，调整魔力
    local current = Made.getMaryoku(player)
    if current > max then
        Made.changeMaryoku(player, max - current, reason .. "_adjust")
    end
    
    -- 触发上限变化事件
    room.logic:trigger(Made.MaryokuMaxChanged, player, {
        who = player,
        old_max = old_max,
        new_max = max,
        reason = reason
    })
end

-- 优化后的变身函数
---@param player ServerPlayer 进行变身的角色
---@param target_general string 目标武将
---@param reason string 原因（通常为技能名）
---@return boolean --是否成功变身
Made.enterHenshin = function(player, target_general, reason)
    local room = player.room
    
    -- 检查是否已变身
    if Made.isHenshin(player) then return false end
    
    -- 检查魔力是否达到上限
    --if Made.getMaryoku(player) < Made.getMaryokuMax(player) then return false end
    
    -- 检查目标武将是否存在
    local target_general_obj = Fk.generals[target_general]
    if not target_general_obj then
        room:sendLog{ type = "#HenshinInvalidTarget", from = player.id }
        return false
    end
    
    -- 触发变身前事件
    local pre_data = {
        who = player,
        target_general = target_general,
        reason = reason
    }
    room.logic:trigger(Made.HenshinEntering, player, pre_data)
    
    if pre_data.prevented then return false end
    
    -- 记录当前状态（原形态）
    local original_general = player.general
    local original_deputy = player.deputyGeneral
    local original_hp = player.hp
    local original_max_hp = player.maxHp
    
    -- 获取形态存档表，如果不存在则创建
    local form_data = player:getTableMark("shine__form_data") or {}
    
    -- 保存原形态数据
    form_data[original_general] = {
        hp = original_hp,
        max_hp = original_max_hp,
        deputy = original_deputy,
        timestamp = os.time()
    }
    
    -- 获取目标形态的存档数据（如果存在）
    local target_form_data = form_data[target_general] or {}
    local target_hp = target_form_data.hp or target_general_obj.maxHp
    local target_max_hp = target_form_data.max_hp or target_general_obj.maxHp
    local target_deputy = target_form_data.deputy
    
    -- 弃置判定区所有牌
    if not player.dead and #player:getCardIds("j") > 0 then
      player:throwAllCards("j", reason)
    end
    
    -- 记录变身信息
    room:setPlayerMark(player, "shine__original_general", original_general)
    if original_deputy then
        room:setPlayerMark(player, "shine__original_deputy", original_deputy)
    end
    room:setPlayerMark(player, "shine__target_general", target_general)
    
    -- 变身
    room:changeHero(player, target_general, false, false, true, true, true)
    
    -- 设置目标形态的体力和体力上限
    if player.maxHp ~= target_max_hp then
        room:setPlayerProperty(player, "maxHp", target_max_hp)
    end
    if player.hp ~= target_hp then
        room:setPlayerProperty(player, "hp", target_hp)
    end
    
    -- 标记变身状态
    room:setPlayerMark(player, "shine__henshin_state", 1)
    
    -- 更新形态存档表
    room:setPlayerMark(player, "shine__form_data", form_data)
    
    -- 触发变身后事件
    room.logic:trigger(Made.HenshinEntered, player, {
        who = player,
        original_general = original_general,
        target_general = target_general,
        reason = reason
    })
    
    return true
end

-- 优化后的退出变身函数
---@param player ServerPlayer 退出变身的角色
---@param reason string 原因（通常为技能名）
---@return boolean --是否成功退出
Made.exitHenshin = function(player, reason)
    local room = player.room
    
    -- 检查是否在变身状态
    if not Made.isHenshin(player) then return false end
    
    -- 触发退出变身事件
    local pre_data = {
        who = player,
        reason = reason
    }
    room.logic:trigger(Made.HenshinExiting, player, pre_data)
    
    if pre_data.prevented then return false end
    
    -- 获取变身信息
    local original_general = player:getMark("shine__original_general")
    local original_deputy = player:getMark("shine__original_deputy")
    local target_general = player:getMark("shine__target_general")
    
    -- 检查变身信息是否完整
    if not original_general or not target_general then
        room:sendLog{ type = "#HenshinDataCorrupted", from = player.id }
        return false
    end
    
    -- 获取形态存档表
    local form_data = player:getTableMark("shine__form_data") or {}
    
    -- 保存当前变身形态的数据
    form_data[target_general] = {
        hp = player.hp,
        max_hp = player.maxHp,
        deputy = player.deputyGeneral,
        timestamp = os.time()
    }
    
    -- 获取原形态的存档数据
    local original_form_data = form_data[original_general] or {}
    local original_hp = original_form_data.hp or (Fk.generals[original_general] and Fk.generals[original_general].maxHp) or player.maxHp
    local original_max_hp = original_form_data.max_hp or (Fk.generals[original_general] and Fk.generals[original_general].maxHp) or player.maxHp
    local original_deputy_actual = original_form_data.deputy or original_deputy
    
    -- 变回原形态
    room:changeHero(player, original_general, false, false, true, true, true)
    
    -- 如果原形态有副将，也恢复
    if original_deputy_actual and original_deputy_actual ~= "" then
        room:setPlayerProperty(player, "deputyGeneral", original_deputy_actual)
    end
    
    -- 恢复原形态的体力和体力上限
    if player.maxHp ~= original_max_hp then
        room:setPlayerProperty(player, "maxHp", original_max_hp)
    end
    if player.hp ~= original_hp then
        room:setPlayerProperty(player, "hp", original_hp)
    end
    
    -- 清除变身状态标记
    room:setPlayerMark(player, "shine__henshin_state", 0)
    room:setPlayerMark(player, "shine__original_general", 0)
    room:setPlayerMark(player, "shine__original_deputy", 0)
    room:setPlayerMark(player, "shine__target_general", 0)
    
    -- 更新形态存档表
    room:setPlayerMark(player, "shine__form_data", form_data)
    
    -- 触发退出变身后事件
    room.logic:trigger(Made.HenshinExited, player, {
        who = player,
        reason = reason,
        from_general = target_general,
        to_general = original_general
    })
    
    return true
end

-- 新增函数：获取角色的所有形态数据
---@param player Player
---@return table --形态数据表
Made.getFormData = function(player)
    return player:getTableMark("shine__form_data") or {}
end

-- 新增函数：检查角色是否曾经变身过某个形态
---@param player Player
---@param general_name string 武将名
---@return boolean
Made.hasTransformedTo = function(player, general_name)
    local form_data = Made.getFormData(player)
    return form_data[general_name] ~= nil
end

-- 新增函数：获取角色当前变身的目标武将（如果正在变身）
---@param player Player
---@return string|nil
Made.getCurrentHenshinTarget = function(player)
    if not Made.isHenshin(player) then return nil end
    return player:getMark("shine__target_general")
end

-- 新增函数：获取角色当前的原形态武将（如果正在变身）
---@param player Player
---@return string|nil
Made.getCurrentOriginalGeneral = function(player)
    if not Made.isHenshin(player) then return nil end
    return player:getMark("shine__original_general")
end

-- 获取称号
---@param player Player 需要查询称号的目标
Made.getHonor = function (player)
    local general = player.general
    local name = Fk:translate("#"..general, "zh_CN")
    if name ~= "#"..general and name ~= "" then
    return name
    end
    return nil
end

--[[ 同时注册到全局 fk 表，确保其他模块可以访问
fk.MaryokuChanging = MaryokuChanging
fk.MaryokuChanged = MaryokuChanged
fk.MaryokuMaxChanged = MaryokuMaxChanged
fk.HenshinEntering = HenshinEntering
fk.HenshinEntered = HenshinEntered
fk.HenshinExiting = HenshinExiting
fk.HenshinExited = HenshinExited
fk.MaryokuConsumed = MaryokuConsumed]]

return Made